package cc.telecomdigital.tdstock.trading.Services;

import java.util.ArrayList;
import java.util.List;

import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;

import cc.telecomdigital.tdstock.R;
import cc.telecomdigital.tdstock.Framework.UniqueItem.DeviceInfo;
import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;
import cc.telecomdigital.tdstock.Services.SoapTransport;

import cc.telecomdigital.tdstock.trading.Common.Trade_AppConstant;
import cc.telecomdigital.tdstock.trading.Common.Trade_StockHoldItem;
import cc.telecomdigital.tdstock.trading.Common.Trade_StockPortfolioRecord;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

public class TradeGetPortfolio
{
	private final String	LOG_TAG	= "TradeGetPortfolio";

	// Call back interface
	public interface ITradeGetPortfolioResponse
	{
		// if iSuccessfulSend == false, it means the there is a communication
		// error
		// do not consider the iReponse as valid response;
		void ResponseFunc(boolean iSuccessfulSend,
				TradeGetPortfolioResult iResponse);
	}

	public class TradeGetPortfolioResult
	{
		public boolean					Result;
		public String					StatusCode;
		public String					BrokerMessage;
		public Trade_StockPortfolioRecord	portfolio;

		public TradeGetPortfolioResult(boolean iResult, String iStatusCode,
				String iBrokerMessage, Trade_StockPortfolioRecord iPortfolio)
		{
			Result = iResult;
			StatusCode = iStatusCode;
			BrokerMessage = iBrokerMessage;
			if (iPortfolio != null)
				portfolio = new Trade_StockPortfolioRecord(iPortfolio);
			else
				portfolio = null;
		}
	}

	private final boolean debugMode = false;
	private SoapObject				soapRequest;
	private Context				callerContext;
	private boolean				demoData	= false;
	private Handler				messageHandler;
	private ITradeGetPortfolioResponse	responseHandler;

	public TradeGetPortfolio(Context iContext)
	{
		callerContext = iContext;

		soapRequest = new SoapObject(TradeAppInfo.NAMESPACE, "Portfolio");
		soapRequest.addProperty("DeviceID",
				TradeAppInfo.GetDeviceID(iContext));
		soapRequest.addProperty("UIN", TradeAppInfo.GetUIN());
		soapRequest.addProperty("ProtocolVer",
				TradeAppInfo.GetProtocolVersion());
		soapRequest.addProperty("BrokerID", TradeAppInfo.BrokerID);
		soapRequest.addProperty("Language", DeviceInfo.GetLanguageString());
	}

	public void SetUserInformation(String iName)
	{
		soapRequest.addProperty("ClientID", iName);
	}

	public void SetUserInformation(String iName, String iPassword)
	{
		soapRequest.addProperty("ClientID", iName);
		soapRequest.addProperty("ClientPassword", iPassword);
	}

	public void Dispose()
	{		
		messageHandler = null;
		if (debugMode)
			TDStockLog.i(LOG_TAG, "We have no reference anymore");	
	}
		
	// If we are running a demo version, the iUseDemoData could be a fake send
	public void SendRequest(boolean iUseDemoData,
			ITradeGetPortfolioResponse iTradeGetPortfolioResponse)
	{
		demoData = iUseDemoData;
		responseHandler = iTradeGetPortfolioResponse;
		messageHandler = new Handler()
		{
			@Override
			public void handleMessage(Message msg)
			{
				if (responseHandler == null)
					return;

				switch (msg.what)
				{
					case REQUEST_DATA_SENT_FAIL:
						responseHandler.ResponseFunc(false, null);
						break;

					case REQUEST_DATA_SENT_SUCCESS:
						responseHandler.ResponseFunc(true,
								(TradeGetPortfolioResult) msg.obj);
						break;
				}
			}
		};
		// Start the Thread
		Thread internalThreadObj = new Thread()
		{
			// On purpose pass in to a message handler, so the thread can sleep or be
			// killed
			@Override
			public void run()
			{
				Message msg;
				TradeGetPortfolioResult infoData;

				// Provide success or fail reply
				msg = new Message();
				infoData = SendData(demoData);
				if ((infoData.Result == false) || (infoData.StatusCode == null)
						|| (infoData.StatusCode.length() == 0))
					msg.what = REQUEST_DATA_SENT_FAIL;
				else
				{
					msg.what = REQUEST_DATA_SENT_SUCCESS;
					msg.obj = infoData;
				}
				messageHandler.sendMessage(msg);
			}		
		};
		internalThreadObj.setName(LOG_TAG);
		internalThreadObj.start();
	}

	private final int	REQUEST_DATA_SENT_FAIL		= 0;
	private final int	REQUEST_DATA_SENT_SUCCESS	= 1;
	
	private Trade_StockPortfolioRecord GetDemoRecord()
	{
		Trade_StockPortfolioRecord demoRecord;
		Trade_StockHoldItem stockRecord;

		TDStockLog.d(LOG_TAG, "Using Prepared Data");
		demoRecord = new Trade_StockPortfolioRecord("37422910.00", "288000.00", 
											"1188000.00", null, "4250");

		stockRecord = new Trade_StockHoldItem("00001", "長江實業", "CHEUNG KONG",
				"5000", "118.7", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("00005", "匯豐控股",
				"HSBC HOLDINGS", "1200", "81.85", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("00006", "電能實業",
				"POWER ASSETS", "5000", "49.20", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("00012", "恒基地產",
				"HENDERSON LAND", "-4000", "56.20", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("00020", "會德豐", "WHEELOCK",
				"9000", "28.85", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("00939", "建設銀行", "CCB", "9000",
				"7.170", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("00941", "中移動", "CHINA MOBILE",
				"3000", "81.95", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("02888", "渣打集團", "STANCHART",
				"-450", "227.0", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);
		stockRecord = new Trade_StockHoldItem("03988", "中行",
				"BANK OF CHINA ", "2000", "4.360", "HKD", "1");
		demoRecord.AddStockRecordToTheList(stockRecord);

		return demoRecord;
	}
	
	private TradeGetPortfolioResult SendData(boolean iDemoData)
	{
		//Prevent multiple call for object
		synchronized(TradeAppInfo.padLock)
		{
			SoapSerializationEnvelope envelope;
			TradeGetPortfolioResult resultCode;
			Trade_StockPortfolioRecord portRecord;
	
			portRecord = null;
			resultCode = null;
			if (iDemoData == true)
			{
				try
				{
					Thread.sleep(Trade_AppConstant.demoHoldTime);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
					TDStockLog.e(LOG_TAG, "SendData=>Exception: " + e.toString());
				}				
				resultCode = new TradeGetPortfolioResult(true, "0", null,
						GetDemoRecord());
				return resultCode;
			}
	
			if (DeviceInfo.IsNetworkAvailable(callerContext) == false)
			{
				resultCode = new TradeGetPortfolioResult(false, null, null, null);
				return resultCode;
			}
	
			envelope = new SoapSerializationEnvelope(TradeAppInfo.SOAP_VERSION);
	
			// Set packet ID
			soapRequest.addProperty("SeqNo", TradeAppInfo.GetSeqNo(true));
			// Last modification of the time
			soapRequest.addProperty(
					"Timestamp",
					TradeAppInfo.GetCurrentTimeStamp() + ","
							+ TradeAppInfo.GetSessionToken());
			envelope.setOutputSoapObject(soapRequest);
	
			String accountCode;
			String statusCode;
			String brokerMessage;
	
			String purchasePower;
			//String availCash;
			String prevMarketValue;
			String hkdCash;		
			String usdCash;
			String cnyCash;
			// String osBuy;
			List<Trade_StockHoldItem> stockList;
	
			accountCode = null;
			statusCode = null;
			brokerMessage = null;
	
			purchasePower = null;
			//availCash = null;
			prevMarketValue = null;
			hkdCash = null;		
			usdCash = null;
			cnyCash = null;
			// osBuy = null;
			stockList = null;
			try
			{
				SoapObject resultsRequestSOAP;
				SoapObject soapResults;
				SoapObject stockGroup;
	
				SoapTransport dataTransfer;
				
				if (TradeAppInfo.useSSLSetting)
					dataTransfer = new SoapTransport( callerContext, TradeAppInfo.GetURLAddress(true), 
						   				    		TradeAppInfo.SOAP_COMMUNIC_Timeout, R.raw.ca_stock);
				else
					dataTransfer = new SoapTransport( callerContext, TradeAppInfo.GetURLAddress(false), 
										   		TradeAppInfo.SOAP_COMMUNIC_Timeout);
				
				if (debugMode)
					TDStockLog.i(LOG_TAG, "Try sending Data");
				
				dataTransfer.SendData(TradeAppInfo.SOAP_SERVICENAME, envelope);			
				
				resultsRequestSOAP = (SoapObject) envelope.bodyIn;
				if (debugMode)
					TDStockLog.i(LOG_TAG, "Parsing Data");			
				soapResults = (SoapObject) resultsRequestSOAP
						.getProperty("PortfolioResult");
	
				// If the reference number is not the one we create
				statusCode = TradeAppInfo.GetSoapProperty(soapResults, LOG_TAG,
						"StatusCode");
	
				if (statusCode.equals("0") == false)
					brokerMessage = TradeAppInfo.GetSoapProperty(soapResults,
							LOG_TAG, "Message");
				else
				{
					accountCode = TradeAppInfo.GetSoapProperty(soapResults,
							LOG_TAG, "AccountCode");
					purchasePower = TradeAppInfo.GetSoapProperty(soapResults,
							LOG_TAG, "PurchasePower");
	//				availCash = TradeAppInfo.GetSoapProperty(soapResults,
	//						LOG_TAG, "AvailCash");
					prevMarketValue = TradeAppInfo.GetSoapProperty(soapResults,
							LOG_TAG, "PrevMarketValue");
					usdCash = TradeAppInfo.GetSoapProperty(soapResults,
							LOG_TAG, "usdcash");
					cnyCash = TradeAppInfo.GetSoapProperty(soapResults,
							LOG_TAG, "cnycash");				
					hkdCash = TradeAppInfo.GetSoapProperty( soapResults,
					 		LOG_TAG, "Cash");
					// osBuy = TradeAppInfo.GetSoapProperty( soapResults,
					// LOG_TAG, "OSBuy");
	
					try
					{
						stockGroup = (SoapObject) soapResults
								.getProperty("stocks");
						if (stockGroup != null)
						{
							int index, count;
							Trade_StockHoldItem stockItem;
							SoapObject singleStock;
							String stockCode;
							String onHand;
							String engName;
							String chnName;
							String prevPrice;
							String currencyType;
							String rate;
	
							count = stockGroup.getPropertyCount();
							if (count != 0)
								stockList = new ArrayList<Trade_StockHoldItem>();
							for (index = 0; index < count; index++)
							{
								// Get the index attribute
								singleStock = (SoapObject) stockGroup
										.getProperty(index);
								stockCode = TradeAppInfo.GetSoapProperty(
										singleStock, LOG_TAG, "StockCode");
								onHand = TradeAppInfo.GetSoapProperty(
										singleStock, LOG_TAG, "OnHand");
								engName = TradeAppInfo.GetSoapProperty(
										singleStock, LOG_TAG, "EngName");
								chnName = TradeAppInfo.GetSoapProperty(
										singleStock, LOG_TAG,
										"ChineseName");
								prevPrice = TradeAppInfo.GetSoapProperty(
										singleStock, LOG_TAG, "Prevclose");
								rate = TradeAppInfo.GetSoapProperty(
										singleStock, LOG_TAG, "Rate");
								currencyType = TradeAppInfo.GetSoapProperty(
											singleStock, LOG_TAG, "Cur");							
								stockItem = new Trade_StockHoldItem(
										stockCode, chnName, engName,
										onHand, prevPrice, currencyType, rate);
								stockList.add(stockItem);
							}
						}
					}
					catch (Exception ie)
					{
						// More likely it does not include
						ie.printStackTrace();
					}
				}
			}
			catch (java.net.SocketTimeoutException e)
			{
				e.printStackTrace();
				TDStockLog.e(LOG_TAG, "Timeout: " + e.toString());
				resultCode = new TradeGetPortfolioResult(false, null, null, null);
				return resultCode;
			}
			catch (Exception e)
			{
				e.printStackTrace();
				TDStockLog.e(LOG_TAG, e.toString());
				resultCode = new TradeGetPortfolioResult(false, null, null, null);
				return resultCode;			
			}
	
			portRecord = new Trade_StockPortfolioRecord(prevMarketValue, purchasePower, 
												hkdCash, usdCash, cnyCash);
			portRecord.SetStockPorfolioAccountCode(accountCode);
			portRecord.SetStockHoldList(stockList);
	
			resultCode = new TradeGetPortfolioResult(true, statusCode,
					brokerMessage, portRecord);
	
			return resultCode;
		}
	}
}
